package com.cyper.mvnbook.account.service;

import com.cyper.mvnbook.account.captcha.AccountCaptchaException;
import com.cyper.mvnbook.account.captcha.AccountCaptchaService;
import com.cyper.mvnbook.account.captcha.RandomGenerator;
import com.cyper.mvnbook.account.email.AccountEmailException;
import com.cyper.mvnbook.account.email.AccountEmailService;
import com.cyper.mvnbook.account.persist.Account;
import com.cyper.mvnbook.account.persist.AccountPersistException;
import com.cyper.mvnbook.account.persist.AccountPersistService;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by cyper on 11/23/14.
 */
public class AccountServiceImpl implements AccountService {
    private AccountPersistService accountPersistService;
    private AccountEmailService accountEmailService;
    private AccountCaptchaService accountCaptchaService;

    private Map<String, String> activationMap = new HashMap<String, String>();

    public String generateCaptchaKey() throws AcccountServiceException {

        try {
            return accountCaptchaService.generateCaptchaKey();
        } catch (AccountCaptchaException e) {
            throw new AcccountServiceException("Unable to generate captcha key.", e);
        }
    }

    public byte[] generateCaptchaImage(String captchaKey) throws AcccountServiceException {

        try {
            return accountCaptchaService.generateCaptchaImage(captchaKey);
        } catch (AccountCaptchaException e) {
            throw new AcccountServiceException("Unable to generate captcah image.", e);
        }
    }

    public void signUp(SignUpRequest signUpRequest) throws AcccountServiceException {
        try {
            if (!signUpRequest.getPassword().equals(signUpRequest.getConfirmPassword())) {
                throw new AcccountServiceException("2 passwords do not match.");
            }
            if (!accountCaptchaService.validateCaptcha(signUpRequest.getCaptchaKey(), signUpRequest.getCaptchaValue())) {
                throw new AcccountServiceException("Incorrect captcha.");
            }
            Account account = new Account();
            account.setId(signUpRequest.getId());
            account.setEmail(signUpRequest.getEmail());
            account.setName(signUpRequest.getName());
            account.setPassword(signUpRequest.getPassword());
            account.setActivated(false);

            accountPersistService.createAccount(account);
            String activationId = RandomGenerator.getRandomString();
            activationMap.put(activationId, account.getId());

            String link = signUpRequest.getActivateServiceUrl().endsWith("/") ? signUpRequest.getActivateServiceUrl() + activationId : signUpRequest.getActivateServiceUrl() + "?key=" + activationId;
            accountEmailService.sendMail(account.getEmail(), "Please activate your account", link);


        } catch (AccountCaptchaException e) {
            throw new AcccountServiceException("Unable to validate captcha.", e);
        } catch (AccountPersistException e) {
            throw new AcccountServiceException("Unable to create account.", e);
        } catch (AccountEmailException e) {
            throw new AcccountServiceException("Unable to send activation mail.", e);
        }
    }

    public void activate(String activateNumber) throws AcccountServiceException {
        String accountId = activationMap.get(activateNumber);
        if (accountId == null) {
            throw new AcccountServiceException("Invalid account activiation ID.");
        }

        try {
            Account account = accountPersistService.readAccount(accountId);
            account.setActivated(true);
            accountPersistService.updateAccount(account);
        } catch (AccountPersistException e) {
            throw new AcccountServiceException("Unable to activate account.");
        }
    }

    public void login(String id, String password) throws AcccountServiceException {
        try {
            Account account = accountPersistService.readAccount(id);
            if (account == null) {
                throw new AcccountServiceException("Account does not exist.");
            }
            if (!account.isActivated()) {
                throw new AcccountServiceException("Account is disabled.");
            }
            if (!account.getPassword().equals(password)) {
                throw new AcccountServiceException("Incorrect password.");
            }
        } catch (AccountPersistException e) {
            throw new AcccountServiceException("Unabled to login.", e);
        }
    }


    public void setAccountCaptchaService(AccountCaptchaService accountCaptchaService) {
        this.accountCaptchaService = accountCaptchaService;
    }

    public void setAccountEmailService(AccountEmailService accountEmailService) {
        this.accountEmailService = accountEmailService;
    }

    public void setAccountPersistService(AccountPersistService accountPersistService) {
        this.accountPersistService = accountPersistService;
    }
}
